package com.shiroexploit.gui;

import com.shiroexploit.util.Config;
import com.shiroexploit.util.HttpRequest;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import java.io.IOException;

public class ConfigPane {
    private VBox vBox = new VBox();
    private StartPane previousPane;
    private ToggleGroup typeGroup = new ToggleGroup();
    private RadioButton cyeButton = new RadioButton("和CEYE配合使用");
    private RadioButton oobServiceButton = new RadioButton("和自实现的OOB Service配合使用");
    private GridPane middlePane = new GridPane();
    private TextField ipAddress = new TextField();
    private TextField httpServicePort = new TextField();
    private TextField JRMPListenerPort = new TextField();
    private GridPane bottomPane = new GridPane();
    private ToggleGroup skipIfFound = new ToggleGroup();
    private RadioButton yesForSkip = new RadioButton("是");
    private RadioButton noForSkip = new RadioButton("否");
    private ToggleGroup usingJRMP = new ToggleGroup();
    private Button checkKeyButton = new Button("使用第三方 DNSLog 平台筛选出唯一 Key（可选)");
    RadioButton yesForJRMP = new RadioButton("是");
    RadioButton noForJRMP = new RadioButton("否");
    Button previous = new Button("上一步");
    Button next = new Button("下一步");

    public void update(){
        // 等于0表示使用的是ceye
        if(Config.getInstance().getOobType() == 0){
            typeGroup.selectToggle(cyeButton);
            middlePane.setDisable(true);
            bottomPane.setDisable(true);
        }else{
            typeGroup.selectToggle(oobServiceButton);
            String address = Config.getInstance().getOOBServerAddress();
            if(address != null && !address.equals("")){
                ipAddress.setText(address);
            }

            int httpPort = Config.getInstance().getHTTPServicePort();
            if(httpPort != 0){
                httpServicePort.setText(httpPort + "");
            }

            int JRMPPort = Config.getInstance().getHTTPServicePort();
            if(JRMPPort != 0){
                httpServicePort.setText(JRMPPort + "");
            }

            boolean flag1 = Config.getInstance().isUseJRMP();
            if(flag1){
                usingJRMP.selectToggle(yesForJRMP);
            }else{
                usingJRMP.selectToggle(noForJRMP);
            }

            boolean flag2 = Config.getInstance().isSkipIfFound();
            if(flag2){
                skipIfFound.selectToggle(yesForSkip);
            }else{
                skipIfFound.selectToggle(noForSkip);
            }

            int vulType = Config.getInstance().getVulType();
            if(vulType == 0){
                checkKeyButton.setDisable(false);
            }else{
                checkKeyButton.setDisable(true);
            }
        }
    }

    public ConfigPane(StartPane pane){
        this.previousPane = pane;
        drawPane();
        addListeners();
    }

    public Pane getPane(){
        return this.vBox;
    }

    private void addListeners(){
        checkKeyButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                Stage currentStage = (Stage) vBox.getScene().getWindow();
                FuzzingKeyPange fuzzingKeyPange = new FuzzingKeyPange(currentStage);

                Stage newStage = new Stage();
                newStage.setTitle(Config.getInstance().getRequestInfo().getRequestURL());
                newStage.setScene(new Scene(fuzzingKeyPange.getPane(), 580,350));

                newStage.setOnShown(new EventHandler<WindowEvent>() {
                    @Override
                    public void handle(WindowEvent event) {
                        currentStage.hide();
                    }
                });

                newStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
                    @Override
                    public void handle(WindowEvent event) {
                        currentStage.show();
                    }
                });

                newStage.show();
            }
        });

        typeGroup.selectedToggleProperty().addListener(new ChangeListener<Toggle>() {
            @Override
            public void changed(ObservableValue<? extends Toggle> observable, Toggle oldValue, Toggle newValue) {
                if(newValue == cyeButton){
                    middlePane.setDisable(true);
                    bottomPane.setDisable(true);
                }else{
                    middlePane.setDisable(false);
                    bottomPane.setDisable(false);
                }
            }
        });

        previous.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                previousPane.update();
                Stage currentStage = (Stage)vBox.getScene().getWindow();
                currentStage.close();
                Stage previous = (Stage)previousPane.getPane().getScene().getWindow();
                previous.show();
            }
        });

        next.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                if(typeGroup.getSelectedToggle() == cyeButton){
                    Config.getInstance().setOobType(0);
                }

                if(typeGroup.getSelectedToggle() == oobServiceButton){
                    String ip = ipAddress.getText();
                    String httpPort = httpServicePort.getText();
                    String JRMPPort = JRMPListenerPort.getText();

                    if(ip == null || ip.trim().equals("")){
                        PromptMessageUI.getAlert("输入错误","IP地址不能为空");
                        return;
                    }

                    if(httpPort == null || httpPort.trim().equals("")){
                        PromptMessageUI.getAlert("输入错误","HTTPService端口不能为空");
                        return;
                    }

                    if(JRMPPort == null || JRMPPort.trim().equals("")){
                        PromptMessageUI.getAlert("输入错误","JRMPListener端口不能为空");
                        return;
                    }

                    if(!validatePortInput(httpPort, JRMPPort)){
                        PromptMessageUI.getAlert("输入错误","您输入的端口格式不正确");
                        return;
                    }

                    if(!validateOOBServerConnection(ip, Integer.parseInt(httpPort))){
                        PromptMessageUI.getAlert("连接失败","无法连接到您指定的OOB Server，请确定配置是否正确");
                        return;
                    }

                    Config.getInstance().setOobType(1);
                    Config.getInstance().setOOBServerAddress(ip);
                    Config.getInstance().setHTTPServicePort(Integer.parseInt(httpPort));
                    Config.getInstance().setJRMPServicePort(Integer.parseInt(JRMPPort));
                    Config.getInstance().setUseJRMP(usingJRMP.getSelectedToggle() == yesForJRMP ? true : false);
                    Config.getInstance().setSkipIfFound(skipIfFound.getSelectedToggle() == yesForSkip ? true : false);
                }

                Stage newStage = new Stage();
                MainPane mainPane = new MainPane();
                newStage.setTitle(Config.getInstance().getRequestInfo().getRequestURL());
                newStage.setScene(new Scene(mainPane.getPane(), 800,600));
                //close第一步和第二步的2个界面
                Stage currentStage = (Stage)vBox.getScene().getWindow();
                currentStage.close();
                Stage previousStage = (Stage)previousPane.getPane().getScene().getWindow();
                previousStage.close();
                newStage.setOnShown(new EventHandler<WindowEvent>() {
                    @Override
                    public void handle(WindowEvent event) {
                        Platform.runLater(new Runnable() {
                            @Override
                            public void run() {
                                mainPane.startRuning();
                            }
                        });
                    }
                });


                //关闭 Stage 时结束所有正在执行的任务
                //参考 https://stackoverflow.com/questions/12153622/how-to-close-a-javafx-application-on-window-close
                newStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
                    @Override
                    public void handle(WindowEvent event) {
                        Platform.exit();
                        System.exit(0);
                    }
                });

                newStage.show();
            }
        });
    }

    public void drawPane(){
        cyeButton.setToggleGroup(typeGroup);
        oobServiceButton.setToggleGroup(typeGroup);

        vBox.getChildren().addAll(cyeButton, oobServiceButton);
        vBox.setMargin(cyeButton, new Insets(20,0,0,40));
        vBox.setMargin(oobServiceButton, new Insets(20,0,0,40));

        middlePane.setVgap(20);
        middlePane.setHgap(20);

        GridPane.setColumnSpan(checkKeyButton, 2);
        if(Config.getInstance().getVulType() == 1){
            checkKeyButton.setDisable(true);
        }
        middlePane.add(checkKeyButton,0,0);

        Label labelForIP = new Label("IPAddress");
        middlePane.add(labelForIP,0, 1);
        middlePane.add(ipAddress, 1,1);

        Label labelForHTTPPort = new Label("HTTPService Port");
        httpServicePort.setText("8080");
        middlePane.add(labelForHTTPPort,0, 2);
        middlePane.add(httpServicePort, 1,2);

        Label labelForJRMPPort = new Label("JRMPListener Port");
        JRMPListenerPort.setText("8088");
        middlePane.add(labelForJRMPPort,0, 3);
        middlePane.add(JRMPListenerPort, 1,3);
        middlePane.setDisable(true);

        vBox.getChildren().add(middlePane);
        vBox.setMargin(middlePane, new Insets(20, 100, 0,80));

        bottomPane.setVgap(20);
        bottomPane.setHgap(20);

        Label label1 = new Label("找到可用Gadget即停止寻找");
        yesForSkip.setToggleGroup(skipIfFound);
        noForSkip.setToggleGroup(skipIfFound);
        skipIfFound.selectToggle(yesForSkip);
        bottomPane.add(label1, 0, 0);
        bottomPane.add(yesForSkip, 1, 0);
        bottomPane.add(noForSkip, 2,0);


        Label label2 = new Label("是否使用JRMP");
        yesForJRMP.setToggleGroup(usingJRMP);
        noForJRMP.setToggleGroup(usingJRMP);
        usingJRMP.selectToggle(yesForJRMP);
        bottomPane.add(label2, 0, 1);
        bottomPane.add(yesForJRMP, 1, 1);
        bottomPane.add(noForJRMP, 2,1);
        bottomPane.setDisable(true);

        vBox.getChildren().add(bottomPane);
        vBox.setMargin(bottomPane, new Insets(20, 100, 20,80));

         HBox hBox = new HBox();
         hBox.getChildren().addAll(previous, next);
         hBox.setMargin(previous, new Insets(0,20,0,0));
         hBox.setAlignment(Pos.CENTER);
         vBox.getChildren().add(hBox);
    }

    private boolean validateOOBServerConnection(String ip, int port) {
        String url = "http://" + ip + ":" + port + "/echo";
        String result = null;
        try{
            result = HttpRequest.request(url);
        }catch (IOException e){
            return false;
        }

        if(result != null && result.trim().equals("OK")){
            return true;
        }

        return false;
    }

    private boolean validatePortInput(String httpServicePort, String JRMPListener){
        try{
            Integer.parseInt(httpServicePort);
            Integer.parseInt(JRMPListener);
        }catch(NumberFormatException e){
            return false;
        }

        return true;
    }
}
